package testJdk.reflectDemo;

import org.junit.Test;
import testJdk.reflectDemo.bean.Employee;

import java.io.FileReader;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URL;
import java.util.Properties;

/**
 * @version 1.0.0
 * Created by cyd on 2024-07-29 10:27:06
 * @ClassName : testJdk.reflectDemo.Demo1
 * @Description : 类描述
 */
public class Demo1 {


    @Test
    public void getClassObj() throws ClassNotFoundException {
        // 类名.class
        Class<Employee> aClass = Employee.class;
        System.out.println(aClass);

        // 对象.getClass
        Employee employee = new Employee();
        Class<? extends Employee> bClass = employee.getClass();
        System.out.println(bClass);

        // Class.forName("类全名")
        Class<?> cClass = Class.forName("testJdk.reflectDemo.bean.Employee");
        System.out.println(cClass);
    }

    @Test
    public void getClassInfo() throws ClassNotFoundException {
        Class<Employee> aClass = Employee.class;
        System.out.println(aClass);

        String simpleName = aClass.getSimpleName();
        String name = aClass.getName();
        System.out.println(simpleName);
        System.out.println(name);
    }

    @Test
    public void getClassConstructor() throws ClassNotFoundException, NoSuchMethodException {
        // Class.forName("类全名")
        Class<?> aClass = Class.forName("testJdk.reflectDemo.bean.Employee");

        System.out.println("--------获取所有public的构造器--------------");
        Constructor<?>[] constructors = aClass.getConstructors();
        for (Constructor<?> constructor : constructors) {
            System.out.println(constructor);
        }
        System.out.println("----------得到单个构造器-------");
        Constructor<?> constructor = aClass.getConstructor(String.class, Integer.class);
        System.out.println(constructor);

        System.out.println("--------得到所有存在的构造器-----------");
        Constructor<?>[] dcs = aClass.getDeclaredConstructors();
        for (Constructor<?> c : dcs) {
            System.out.println(c);
        }
    }

    @Test
    public void getClassInstance() throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        // Class.forName("类全名")
        Class<?> aClass = Class.forName("testJdk.reflectDemo.bean.Employee");

        System.out.println("----------得到单个构造器-------");
        Constructor<?> constructor = aClass.getConstructor(String.class, Integer.class);
        Object mike = constructor.newInstance("mike", 20);
        System.out.println(mike);

        System.out.println("----------得到单个构造器(私有)-------");
        Constructor<?> ct = aClass.getDeclaredConstructor(String.class);

        System.out.println("----------使用私有构造器构造对象-------");
        // 访问权限设置为true
        ct.setAccessible(true);
        Object jack = ct.newInstance("jack");
        System.out.println(jack);
    }


    @Test
    public void useClassMethods() throws Exception {
        // Class.forName("类全名")
        Class<?> aClass = Class.forName("testJdk.reflectDemo.bean.Employee");

        System.out.println("----------得到所有公共方法-------");
        Method[] methods = aClass.getMethods();
        for (Method method : methods) {
            System.out.println(method);
        }

        System.out.println("----------得到所有方法-------");
        Method[] methods2 = aClass.getDeclaredMethods();
        for (Method method : methods2) {
            System.out.println(method);
        }

        System.out.println("----------得到一个方法-------");
        Method play = aClass.getDeclaredMethod("play", Integer.class);
        System.out.println(play);

        System.out.println("----------得到单个构造器(私有)-------");
        Constructor<?> ct = aClass.getDeclaredConstructor(String.class);

        System.out.println("----------使用私有构造器构造对象-------");
        // 访问权限设置为true
        ct.setAccessible(true);
        Object jack = ct.newInstance("jack");
        System.out.println(jack);

        System.out.println("----------调用私有方法-------");
        play.setAccessible(true);
        play.invoke(jack, 10);
    }

    @Test
    public void handleField() throws Exception {
        // Class.forName("类全名")
        Class<?> aClass = Class.forName("testJdk.reflectDemo.bean.Employee");

        System.out.println("----------得到单个构造器(私有)-------");
        Constructor<?> ct = aClass.getDeclaredConstructor(String.class);

        System.out.println("----------使用私有构造器构造对象-------");
        // 访问权限设置为true
        ct.setAccessible(true);
        Object jack = ct.newInstance("jack");
        System.out.println(jack);

        System.out.println("----------使用私有成员变量-------");
        Field name = aClass.getDeclaredField("name");
        name.setAccessible(true);
        System.out.println(name.get(jack));
        // 使用反射的成员变量，给对象换成员变量值
        name.set(jack, "cyd");
        System.out.println(jack);
    }

    @Test
    public void reflectFromProperties() throws Exception {

        System.out.println("----------读取配置文件-------");
        Properties pp = new Properties();
        URL resourceRoot = this.getClass().getClassLoader().getResource("");
        System.out.println(resourceRoot);
        pp.load(new FileReader("src/main/java/testJdk/reflectDemo/config/reflectDemo.properties"));
        System.out.println(pp);
        String classname = pp.getProperty("classname");
        String methodname = pp.getProperty("methodname");

        System.out.println("----------得到class对象-------");
        Class<?> aClass = Class.forName(classname);
        System.out.println(aClass);

        System.out.println("----------构造对象-------");
        Object obj = aClass.newInstance();

        System.out.println("----------得到一个方法-------");
        Method method = aClass.getDeclaredMethod(methodname);
        System.out.println(method);

        System.out.println("----------调用方法-------");
        method.invoke(obj);
    }
}
